<?php
/**
 * User class.
 *
 * 
 * 
 * Responsible for the creation, reading, updating, deletion, and management of the Users.

 * 
 * PHP version 5
 *
 * LICENSE: This source file is subject to version 3.01 of the PHP license
 * that is available through the world-wide-web at the following URI:
 * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
 * the PHP License and are unable to obtain it through the web, please
 * send a note to license@php.net so we can mail you a copy immediately.
 *
 * @package    Subbear Subscription Management
 * @author     Shawn Wernig ( shawn@eggplantstudios.ca )
 * @copyright  2013 
 * @license    http://www.eggplantstudios.ca
 * @version    2.0
 */

 
class User {

    public $user_id;
    
    public $user_datestamp;
           
    public $firstname;
    public $lastname;
    public $displayname;
    
    public $phone;
    public $email;
    
    
    public $rr;
    public $box;
    public $apt;
    public $street_address;
    public $street;
    
    public $city;
    public $province;
    public $postal_code;
    public $country;
    

    private static $table_name = "_user";
    
    public function __construct() {
    }
    
    
    /* --------------------------------------- GETS --------------------------------------- */

    /**
     * Returns a friendly name for this user.
     *
     * @return object
     * @author epstudios
     */  
    public function displayname($formal = false) {
        if(!isset($this->displayname)) $this->displayname = $this->firstname . " " . $this->lastname;
        return ($formal) ? htmlspecialchars($this->lastname . ", " . $this->firstname)  :  htmlspecialchars($this->displayname);
    }
    
    /**
     * Outputs the clickable edit link.
     *
     * @return object
     * @author epstudios
     */  
    public function edit_link() {
        global $Controller;
        printf('<a href="%s" title="%s">%s</a>', 
                BASE_URL . $Controller->page_url('edit') . '&user=' . htmlspecialchars( intval($this->user_id)), 
                "Edit subscription for " . htmlspecialchars($this->displayname()), 
                htmlspecialchars($this->displayname())
                );
    }
    public function get_edit_link() {
        global $Controller;
        return BASE_URL . $Controller->page_url('edit') . '&user=' . htmlspecialchars(intval($this->user_id));
    }
    
     /**
     * Outputs the clickable email link.
     *
     * @return object
     * @author epstudios
     */ 
    public function email_link(){
        
        if ( isset($this->email) ) {
          $validator = new Validator;
            return ( $validator->is_email($this->email) ) 
                ? printf (' <a class="show-tool-tip" href="mailto:%s" title="Email %s"><img src="css/ui/email-16.png" /></a>', 
                    $this->email, $this->displayname())
                : false;
        }
        
    }
    
    /**
     * Returns the formatted location
     * 
     * TODO: Update with the tables
     * 
     * @return object
     * @author epstudios
     */ 
    function get_location(){
        $location = '';
        $location .= ( isset($this->box)            && !empty($this->box))              ? "PO Box {$this->box} " : '';
        $location .= ( isset($this->apt)            && !empty($this->apt))              ? "{$this->apt}-" : '';
        $location .= ( isset($this->street_address) && !empty($this->street_address))   ? "$this->street_address" : '';
        $location .= ( isset($this->street)         && !empty($this->street))           ? " $this->street " : '';
        $location .= ( isset($this->rr)             && !empty($this->rr) )              ? "{$this->rr}" : '';
        $location .= ( isset($this->city)           && !empty($this->city) )            ? " {$this->city}" : '';
        $location .= ( isset($this->province)       && !empty($this->province) )        ? " {$this->province}" : '';
        $location .= ( isset($this->country)        && !empty($this->country ))         ? " {$this->country}" : '';
        $location .= ( isset($this->postal_code)    && !empty($this->postal_code ) )    ? " {$this->postal_code}" : '';

                                
       return htmlspecialchars($location);                         
    }
    function get_simple_location(){
        $location = '';
        $location .= ( isset($this->box)            && !empty($this->box))              ? "PO Box {$this->box} " : '';
        $location .= ( isset($this->apt)            && !empty($this->apt))              ? "{$this->apt}-" : '';
        $location .= ( isset($this->street_address) && !empty($this->street_address))   ? "$this->street_address" : '';
        $location .= ( isset($this->street)         && !empty($this->street))           ? " $this->street " : '';
        $location .= ( isset($this->rr)             && !empty($this->rr) )              ? "{$this->rr}" : '';
        
       return htmlspecialchars($location);                         
    }
    function get_region(){
        return htmlspecialchars ( $this->province . ', ' 
                                . $this->country . ' - ' 
                                . $this->postal_code);
    }    
    
    
    
    /**
     * Returns the tablename for this user
     * 
     * @return object
     * @author epstudios
     */ 
    public static function get_tablename() {
        global $TABLE_PREFIX;
        return $TABLE_PREFIX . htmlspecialchars(self::$table_name); 
    }
    
    /**
     * Returns the attributes 
     * 
     * @return object
     * @author epstudios
     */ 
    public function attr($attr) {
        if ( $attr == 'province' ) {
            echo strtoupper( htmlspecialchars($this->$attr) ); 
            return;
        }
        echo htmlspecialchars($this->$attr);
    }
    public function get_attr($attr) {
        if (isset( $this->$attr ) && !empty($this->$attr)) {
            if ( $attr == 'province' ) return strtoupper( htmlspecialchars($this->$attr) ); 
            return ( is_string($this->$attr)) ? $this->$attr : $this->$attr;
        }
    }
    
    
    
    /**
     * Checks if this is a new user.
     * 
     * @return object
     * @author epstudios
     */ 
    public function is_new(){
        return (!isset($this->user_id) || $this->user_id == 0) ? true : false ;
    }
    
    /**
     * Checks if this user has a subscription and returns the status
     * 
     * @return object
     * @author epstudios
     */ 
    public function has_subscription(){
        $sub_status = Subscription::has_subscription($this->user_id);
        return htmlspecialchars($sub_status);
    }
    
    
    
    
    
    
     
    /**
     * Delete a user. Because it can get messy, the logic for this is in the subscription class.
     * 
     * @return object
     * @author epstudios
     */ 
    public static function delete($user_id) {
        global $session;
        
        if ($result && Subscription::delete_by_user_id($user_id) ) {
           $session->add_message("SUCCESS: Allowance #{$user_id} has been removed. ");
           return true;
        }
        return false;
    } 
    

    /**
     * SAVE validates, then updates or inserts the user into the DB. 
     * 
     * 
     * @access public 
     * @return user id
     * 
     */
    public function save(){
        global $session;   
        
        if ( !$this->is_new() && $this->_validate() ) {
             
            $user_id = $this->_update_self();
            if ( $user_id  ){
                $session->add_message("SUCCESS: {$this->displayname} has been successfully saved.");
                return $user_id;
            } else {
                $session->add_message("ERROR: {$this->displayname} could not be saved.");
                return false;
            }
            
            
        } elseif( $this->is_new() && $this->_validate() ) {
            
            $user_id = $this->_update_self();
            if ( $user_id  ){
                $session->add_message("SUCCESS: {$this->displayname} has been successfully saved.");
                return $user_id;
            } else {
                $session->add_message("ERROR: {$this->displayname} could not be saved.");
                return false;
            }
        }
        
        $session->add_message("ERROR: {$this->displayname} has validation errors.");
        return false;
        
    }
    
    /**
     * VALIDATES the class. has the $new parameter to test for duplicate names
     * 
     * TODO: update with db update fields
     * 
     * @access private 
     * @return boolean
     * 
     */
    private function _validate() {
        $validator = new Validator;
        global $session;
        
        //Check that we have valid names ie not duplicated.
        $user_names = User::find_all_names();
        $unique_names = get_class_unique_values($user_names, 'displayname');
        
        // Escape all!
        $validator->escape_class($this);
        
        if ( in_array($this->displayname, $unique_names) && $this->is_new() ) {
            $session->add_message("ERROR: The user {$this->displayname} already exists here: <a href=\"index.php?page=edit&user={$this->user_id}\". If you were wanting to add a new subcription, try adding a new subscription for this user.");
            return false;
        }
        
        
        if ( isset($this->email) && !empty( $this->email )) {
            if( $validator->is_email($this->email) ) {
                $this->email =  $validator->is_email($this->email);
            } else {
                $session->add_message("WARNING: {$this->email} does not appear to be a valid email.");
            }
        }
        
        // required fields: name, lastname, street city prov post country
        $found_errors = 0;
        foreach ( array('First Name' => $this->firstname, 
                        'Last Name' => $this->lastname, 
                        'City' => $this->city, 
                        'Province' => $this->province, 
                        'Postal Code' => $this->postal_code, 
                        'Country' => $this->country) as $key => $value ) {

            if(!$validator->is_valid($value, TRUE)) {
                $session->add_message("ERROR: {$key} is required, but {$value} is not valid.");
                $found_errors ++;
            }
        } 
                        
        if ( $found_errors > 0 ) return false;
                        
        return true;
        
    }

    public static function import_users() {
        if (!isset($_POST['users-csv']) || empty($_POST['users-csv']) ) return false;
        if (!isset($_POST['publication_id']) || empty($_POST['publication_id']) ) return false;
        global $session;
        
        $publication_id = $_POST['publication_id'];
        $dump = $_POST['users-csv'];
        //FNAME,LNAME,Number,Street,RR,Apt,Box,CITY,PROVINCE,POSTCODE,TEL Nmbr,EXPIRE
        $rows = explode("\n", $dump);
        
        // Explode and trim
        foreach( $rows as $row => $value ) {
            $data = explode(",", $value);
            foreach( $data as $k => $v ) $data[$k] = trim( str_replace("  ", " ", $v) );
            $rows[$row] = $data;
        }
        
        foreach($rows as $row) {
   
            $user = User::instantiate( array( 
                  "user_id"         => null,
                  "user_datestamp"  => null,
                  "firstname"       => isset($row[0]) ? $row[0]:null,
                  "lastname"        => isset($row[1]) ? $row[1]:null,
                  "displayname"     => null,
                  "phone"           => isset($row[10]) ? $row[10]:null,
                  "email"           => isset($row[11]) ? $row[11]:null,
                  "rr"              => isset($row[4]) ? $row[4]:null,
                  "apt"             => isset($row[5]) ? $row[5]:null,
                  "box"             => isset($row[6]) ? $row[6]:null,
                  "street_address"  => isset($row[2]) ? $row[2]:null,
                  "street"          => isset($row[3]) ? $row[3]:null,
                  "city"            => isset($row[7]) ? $row[7]:null,
                  "postal_code"     => isset($row[9]) ? $row[9]:null,
                  "province"        => isset($row[8]) ? $row[8]:null,
                  "country"         => 'canada'
                ));
            
            /**
             * 
             * 
             * Save the user.
             */
             
            $user_id = $user->save();
            if ( isset( $user_id ) && !empty( $user_id ) ) {
                
                
                $sub = new Subscription( array(
                        'publication_id'    => $publication_id,
                        'user_id'           => $user_id,
                        'start_week'        => get_weeknum(),
                        'status'            => 'active'
                        ));               
               
               /**
                * 
                * 
                * Save the sub.
                */
                $expires = $row[12];
                $length = ( get_weeknum( strtotime($expires) ) ) - get_weeknum();
                //$length ++; // add a week to balance it out.
                
                if ( $length > 0 ) { // if this is not expired 
                    $sub_id = $sub->save();
                    if ( isset ( $sub_id ) && !empty( $sub_id ) ) {
                        // Save successful - now add some time to it.      
                        $expires = $row[12];
                        $length = ( get_weeknum( strtotime($expires) ) ) - get_weeknum();
                        //$length ++; // add a week to balance it out.

                        $allowance_array = array(
                            'subscription_id' => $sub_id,
                            'total_duration'  => $length,
                            'type' => 'add'
                         );
                        $new_allowance = Allowance::instantiate( $allowance_array );
                        $new_allowance->save();
                        
                        
                    }
                }
            }
        }
        Subscription::scrub_subs($publication_id);
        header('Location: index.php?page=publication'); exit;
    }


    public static function update_user() {
        

        $user = User::instantiate( $_POST );
       
        $user_id = $user->save();
        if ( isset( $user_id ) ) {
            $page = ( isset($_POST['update_user_redirect']) ) ? 'index.php?page=subscriptions' : 'index.php?page=edit';
            header("Location: $page&user=$user_id"); exit; // redirect to new.
        }
        return false;
        
    }
    
    
    /* --------------------------------------- SQL --------------------------------------- */

     private function _update_self() {
        global $db;
        global $session;
        if( !$this->is_new() ) {       
            $sql =  "UPDATE ". self::get_tablename()." ";
            $sql .= "SET firstname='{$this->firstname}', lastname='{$this->lastname}', displayname='{$this->displayname}',
                    phone='{$this->phone}', email='{$this->email}', 
                    rr='{$this->rr}', box='{$this->box}', apt='{$this->apt}', 
                    street_address='{$this->street_address}',  street='{$this->street}', 
                    city='{$this->city}', province='{$this->province}', postal_code='{$this->postal_code}', country='{$this->country}' ";
            $sql .= "WHERE user_id={$this->user_id}";
        } else {
            $sql =  "INSERT INTO ".self::get_tablename()." ";
            $sql .= "(user_datestamp, firstname, lastname, displayname, phone, email, rr, box, apt, street_address, street, city, province, postal_code, country) ";
            $sql .= "VALUES ('".date( 'Y-m-d H:i:s', time() )."', '{$this->firstname}', '{$this->lastname}', '{$this->displayname}', '{$this->phone}', '{$this->email}', '{$this->rr}', '{$this->box}', '{$this->apt}', '{$this->street_address}', '{$this->street}', '{$this->city}', '{$this->province}', '{$this->postal_code}','{$this->country}')";
        }
        
        $result = $db->query( $sql );
        
        if  ($result ) {
                
            if (!$this->is_new() ) {
                return $this->user_id;
            } else {
                $sql =  "SELECT LAST_INSERT_ID() AS user_id FROM ".self::get_tablename();
                
                $result_set = $db->query( $sql );
                $row = $db->fetch_array($result_set);
                return $row['user_id'];
            }
        }
        return false;      
         
    }
    
    
    public static function find_by_id($user_id) {
        global $db;
        
        $objects = self::find_by_sql("SELECT * FROM " . self::get_tablename() . " WHERE user_id=" . $user_id . " LIMIT 1");
        
        if ( $db->affected_rows() > 0 ) {     
            return $objects[0];
        } 
        return false;       
    }

    public static function find_all_names() {
        $objects = self::find_by_sql("SELECT firstname, lastname FROM " . self::get_tablename());
        return $objects;
    }
    
    public static function search_by_column($column, $displayname){
        $objects = self::find_by_sql("SELECT * FROM " . self::get_tablename() . " WHERE {$column} LIKE ('%{$displayname}%')");
        return $objects;
    }
    
    public static function find_by_unsubscribed(){
        // Find expired
        // Find users which don't have subs
        
        global $db;
        
        
       
       // Get unsubscribed:
       $result_set = $db->query( "SELECT * FROM " . self::get_tablename() . " 
       WHERE user_id NOT IN ( SELECT user_id FROM ".Subscription::get_tablename() ." 
       WHERE ( status != 'inactive' ) GROUP BY user_id )" );

       if ( $result_set->num_rows > 0 ) {           
        while ($row = $db->fetch_array($result_set)) {
            $object_array[] = self::instantiate($row, true, false);
        }
        
        //foreach($object_array as $key => $object ) {
           // if ($object->has_subscription()) unset($object_array[$key]);
        //}
               
        // RETURNS the ARRAY OF OBJECTS.
        return $object_array;
       }
       return false;
    }


        
    public static function find_by_search($search){
        global $db;    
        $search = $db->prepare_search_params($search);
        $objects = self::find_by_sql("SELECT * FROM " . self::get_tablename() . " WHERE " . $search );
        return $objects;
    }
    
    public static function find_ids_by_search($search){
        global $db;   
        $result = array(); 
        $search = $db->prepare_search_params($search);
        $result_set = $db->query( "SELECT user_id FROM " . self::get_tablename() . " WHERE " . $search . "ORDER BY user_id ASC");
        
        while ($row = $db->fetch_array($result_set)) {
            $result[] = $row['user_id'];
        }
               
        return $result;
    }
    
    public static function find_by_sql ( $sql="") {
        global $db;
        $result_set = $db->query( $sql );
        
        $object_array = array();
        while ($row = $db->fetch_array($result_set)) {
            $object_array[] = self::instantiate($row);
        }
        // RETURNS AN ARRAY OF OBJECTS.
        return $object_array;
    }
    
    public static function update_by_sql ( $sql="") {
        global $db;
        $result_set = $db->query( $sql );
        
        if ($db->affected_rows() == 1) return TRUE;
        
        return FALSE;
    }

    public static function instantiate ($record) {
        $object = new self;
        
        foreach ( $record as $key=>$value ) {
            if ( $object->has_attribute($key)) {
                $object->$key = $value;
            }
        }
        
        $object->displayname = $object->firstname . " " . $object->lastname;
        
        return $object;
        
    }
    
    private function has_attribute ( $key ) {
        $object_vars = get_object_vars($this);
        return array_key_exists($key, $object_vars);
    }
    
    
    public static function uc_fields( ) {
        if( LIVE ) return false; // do not run on live site.
        $tablename = self::get_tablename();
        $validator = new Validator;
        $users = self::find_by_sql("SELECT * FROM $tablename");
        
        foreach( $users as $user ) {
            $user->firstname = ucwords( $user->firstname );
            $user->lastname = ucwords( $user->lastname );
            $user->displayname = ucwords( $user->displayname );
            $user->street = ucwords( $user->street );
            $user->city = ucwords( $user->city );
            $user->country = ucwords( $user->country );
            
            $user->province  = strtoupper( $user->province );
            $user->postal_code  = strtoupper( $user->postal_code );
            $validator->escape_class($user);
            $user->_update_self();
        }
    } 
    

}
?>